package com.mybatisflex.admin.util;

import com.alibaba.fastjson.JSON;
import com.mybatisflex.admin.AppProperties;
import com.mybatisflex.core.util.StringUtil;
import io.jsonwebtoken.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtUtil {

    private static final String ISUUED_AT = "isuuedAt";
    private static final Logger LOG = LoggerFactory.getLogger(JwtUtil.class);
    private static final Map<String, Object> EMPTY_MAP = new HashMap<>();
    private static final long period = 1000 * 60 * 60 * 24 * 2;// 2 天

    private static SecretKey createSecretKey() {
        byte[] encodedKey = Base64.getEncoder().encode(AppProperties.jwtToken.getBytes(StandardCharsets.UTF_8));
        return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
    }


    public static Map<String, Object> parseToken(String token) {
        SecretKey secretKey = createSecretKey();
        try {
            Claims claims = Jwts.parser()
                    .setSigningKey(secretKey)
                    .parseClaimsJws(token).getBody();

            String jsonString = claims.getSubject();
            if (StringUtil.isNotBlank(jsonString)) {
                return (Map<String, Object>) JSON.parse(jsonString);
            }
        } catch (SignatureException | MalformedJwtException ex) {
            // don't trust the JWT!
            // jwt 签名错误或解析错误，可能是伪造的，不能相信
            LOG.error("Do not trast the jwt. " + ex.getMessage());
        } catch (ExpiredJwtException ex) {
            // jwt 已经过期
            LOG.error("Jwt is expired. " + ex.getMessage());
        } catch (Exception ex) {
            //其他错误
            LOG.error("Jwt parseToken error. " + ex.getMessage());
        }

        return EMPTY_MAP;
    }


    public static String createToken(Map map) {

        SecretKey secretKey = createSecretKey();

        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);

        //追加保存 JWT 的生成时间
        map.put(ISUUED_AT, nowMillis);

        String subject = JSON.toJSONString(map);
        JwtBuilder builder = Jwts.builder()
                .setIssuedAt(now)
                .setSubject(subject)
                .signWith(signatureAlgorithm, secretKey);

        long expMillis = nowMillis + period;
        builder.setExpiration(new Date(expMillis));

        return builder.compact();
    }

}
